#include "stdafx.h"
#include "ServerServicer.h"
#include <atlstr.h>

servicer::servicer(void) 
: m_pServer(NULL), m_pBroadcaster(NULL), m_pObjectManager(NULL), m_pClientManager(NULL) {
}

servicer::~servicer(void) {
}

void servicer::LinkServer(server_base* pServer) {
	assert(m_pServer == NULL);
	assert(pServer != NULL);
	
	m_pServer = pServer;
}

void servicer::LinkBroadcaster(broadcaster* pBroadcaster) {
	assert(m_pBroadcaster == NULL);
	assert(pBroadcaster != NULL);
	
	m_pBroadcaster = pBroadcaster;
}

void servicer::LinkObjectManager(object_manager* pObjectManager) {
	assert(m_pObjectManager == NULL);
	assert(pObjectManager != NULL);
	
	m_pObjectManager = pObjectManager;
}

void servicer::LinkClientManager(client_manager* pClientManager) {
	assert(m_pClientManager == NULL);
	assert(pClientManager != NULL);
	
	m_pClientManager = pClientManager;
}
	
bool servicer::Service(network* pServiceNetwork, service_msg_REQUEST_CODE* ReceiveData) {		
	m_pClientManager->Lock();
	client_manager::client_save_structure* pClientInfo = NULL;	
	pClientInfo = m_pClientManager->SearchClient(pServiceNetwork);
	assert(pClientInfo != NULL);
	
	SERVICE_MESSAGE ReturnMsgType = SR_REQUEST_CODE;
	service_msg_REQUEST_CODE_RETURN ReturnData;
	ReturnData.ClientCode = pClientInfo->ClientCode;

	m_pClientManager->UnLock();



	pServiceNetwork->Send((char*)&ReturnMsgType, sizeof(ReturnMsgType));
	pServiceNetwork->Send((char*)&ReturnData, sizeof(ReturnData));

	return true;
}

bool servicer::Service(network* pServiceNetwork, service_msg_REQUEST_CLIENT* ReceiveData) 
{
	// generate client info array. 
	SERVICE_MESSAGE Msg = SR_REQUEST_CLIENT;
	service_msg_REQUEST_CLIENT_RETURN ReturnData;

	ReturnData.ClientNumber = m_pClientManager->GetClientCount();
	ReturnData.ExtraData  = new service_msg_REQUEST_CLIENT_RETURN::client_info[m_pClientManager->GetClientCount()];

	int i = 0;
	for(m_pClientManager->StartRepeat(); m_pClientManager->Repeat() != NULL; m_pClientManager->NextRepeat())
	{
		ReturnData.ExtraData[i].ClientCode = m_pClientManager->Repeat()->ClientCode;
		ReturnData.ExtraData[i].UdpPort = m_pClientManager->Repeat()->UdpPort;
		ReturnData.ExtraData[i].IP = m_pClientManager->Repeat()->ServiceNetwork->GetLinkIP();
		i++;
	}
	m_pClientManager->EndRepeat();	



	pServiceNetwork->Send((char *) &Msg, sizeof(Msg));	
	pServiceNetwork->Send((char *) &ReturnData, sizeof(ReturnData));
	pServiceNetwork->Send((char *) ReturnData.ExtraData, sizeof(service_msg_REQUEST_CLIENT_RETURN) * ReturnData.ClientNumber);

	delete[] ReturnData.ExtraData;

	return true;
}

bool servicer::Service(network* pServiceNetwork, service_msg_REQUEST_OBJECT* ReceiveData) 
{
	// generate object info array. 
	SERVICE_MESSAGE Msg = SR_REQUEST_OBJECT;
	service_msg_REQUEST_OBJECT_RETURN ReturnData;

	ReturnData.ObjectNumber = m_pObjectManager->GetObjectCount();
	ReturnData.ExtraData = new service_msg_REQUEST_OBJECT_RETURN::object_info[m_pObjectManager->GetObjectCount()];
	
	int i = 0;
	for(m_pObjectManager->StartRepeat(); m_pObjectManager->Repeat() != NULL; m_pObjectManager->NextRepeat())
	{
		ReturnData.ExtraData[i].ObjectID			= m_pObjectManager->Repeat()->ObjectID;
		ReturnData.ExtraData[i].ObjectType			= m_pObjectManager->Repeat()->ObjectType;
		ReturnData.ExtraData[i].OwnerCode			= m_pObjectManager->Repeat()->ObjectOwnerCode;
		ReturnData.ExtraData[i].ObjectExtraLength	= m_pObjectManager->Repeat()->ObjectExtraLength;
		memcpy(	&(ReturnData.ExtraData[i].ObjectExtra), 
				m_pObjectManager->Repeat()->ObjectExtraData, 
				m_pObjectManager->Repeat()->ObjectExtraLength);
		i++;
	}
	m_pObjectManager->EndRepeat();
	


	pServiceNetwork->Send((char *) &Msg, sizeof(Msg));
	pServiceNetwork->Send((char *) &ReturnData, sizeof(ReturnData));
	pServiceNetwork->Send((char *) ReturnData.ExtraData, sizeof(service_msg_REQUEST_OBJECT_RETURN::object_info) * ReturnData.ObjectNumber);

	delete[] ReturnData.ExtraData;

	return true;
}	

bool servicer::Service(network* pServiceNetwork, service_msg_REQUEST_RELAY_LINK* ReceiveData) {
	client_manager::client_save_structure* pClientInfo;

	// search link result. (this service called at client udp link sending.)
	m_pClientManager->Lock();	
	pClientInfo = m_pClientManager->SearchClient(pServiceNetwork);
	assert(pClientInfo != NULL);

	SERVICE_MESSAGE ReturnMsgType = SR_REQUEST_RELAY_LINK;
	service_msg_REQUEST_RELAY_LINK_RETURN ReturnData;

	if(pClientInfo->UdpPort != UDP_NOT_READY) 
		ReturnData.Result = true;	
	else 
		ReturnData.Result = false;



	pServiceNetwork->Send((char*)&ReturnMsgType, sizeof(ReturnMsgType));
	pServiceNetwork->Send((char*)&ReturnData, sizeof(ReturnData));	

	

	CString IPString(inet_ntoa(pServiceNetwork->GetLinkIP()));

	if(ReturnData.Result) {
		// Accept New Client. 
		m_pBroadcaster->PushMessageNewClient(pClientInfo->ServiceNetwork->GetLinkIP(), 
												pClientInfo->ClientCode, pClientInfo->UdpPort);
		m_pServer->DisplayText(_T("[Server] Relay Link Success. Cliend IP[CODE] : %s[%d]. UDP[%d]. Connect Count : %d\n"),
								IPString, pClientInfo->ClientCode, pClientInfo->UdpPort, pClientInfo->UdpConnectCount);
	}
	else
		m_pServer->DisplayText(_T("[Server] Relay Link Failed. Cliend IP[CODE] : %s[%d]. Connect Count : %d\n"),
								IPString, pClientInfo->ClientCode, pClientInfo->UdpConnectCount);

	m_pClientManager->UnLock();
	return true;
}	

bool servicer::Service(network* pServiceNetwork, service_msg_NOTICE_NEW_OBJECT* ReceiveData) {
	int ObjectID = 0;

	ObjectID = m_pObjectManager->NewObject(ReceiveData->ObjectType, ReceiveData->OwnerCode,
								ReceiveData->ExtraLength, ReceiveData->ExtraPtr);

	/*SERVICE_MESSAGE ReturnMsgType = SR_NOTICE_NEW_OBJECT;
	service_msg_NOTICE_NEW_OBJECT_RETURN ReturnData;	
	pServiceNetwork->Send((char*)&ReturnMsgType, sizeof(ReturnMsgType));
	pServiceNetwork->Send((char*)&ReturnData, sizeof(ReturnData));	*/

	m_pServer->DisplayText(_T("[Server] New Object. OID[%d]Type[%d]Owner[%d]\n"), 
									ObjectID, ReceiveData->ObjectType, ReceiveData->OwnerCode);

	m_pBroadcaster->PushMessageNewObject(ObjectID, ReceiveData->ObjectType, 
					ReceiveData->OwnerCode, ReceiveData->ExtraLength, ReceiveData->ExtraPtr); 

	return true;
}

bool servicer::Service(network* pServiceNetwork, service_msg_NOTICE_DEL_OBJECT* ReceiveData) {
	m_pObjectManager->DeleteObject(ReceiveData->ObjectID);

	/*SERVICE_MESSAGE ReturnMsgType = SR_NOTICE_DEL_OBJECT;
	service_msg_NOTICE_DEL_OBJECT_RETURN ReturnData;	
	pServiceNetwork->Send((char*)&ReturnMsgType, sizeof(ReturnMsgType));
	pServiceNetwork->Send((char*)&ReturnData, sizeof(ReturnData));*/

	static unsigned int BeforeDeleteObject = 0;

	if(BeforeDeleteObject == ReceiveData->ObjectID)
		return false;

	m_pServer->DisplayText(_T("[Server] Delete Object. OID[%d]\n"), ReceiveData->ObjectID);

	m_pObjectManager->DeleteObject(ReceiveData->ObjectID);
	m_pBroadcaster->PushMessageDelObject(ReceiveData->ObjectID);
	BeforeDeleteObject = ReceiveData->ObjectID;

	return true;
}

bool servicer::Service(network* pServiceNetwork, service_msg_NOTICE_ACCESS_OFF* ReceiveData) 
{	
	m_pServer->DisplayText(_T("[Server] Access off. Client Code[%d]\n"), ReceiveData->ClientID);	
	m_pServer->DeleteClient(pServiceNetwork);

	return true;
}


bool servicer::Service(network* pServiceNetwork, service_msg_NOTICE_MESSAGE* ReceiveData) 
{
	m_pBroadcaster->PushMessageMessage(ReceiveData->MsgLength, ReceiveData->MsgString);
	return true;
}

bool servicer::Service(network* pServiceNetwork, service_msg_NOTICE_MISSILE_CRUSH* ReceiveData) 
{
	m_pServer->DisplayText(_T("[Server] Missile Crush\n"), ReceiveData->MissileId);
	m_pBroadcaster->PushMessageMissileCrush(ReceiveData->MissileOwner, ReceiveData->MissileId, ReceiveData->TargetClient);
	return true;
}